package com.ly.demo.thread;

import lombok.SneakyThrows;

/**
 * @author liuyang
 * @des
 * @Version 1.0
 * @Date: 17/09/2021 15:02
 */
public class Main {
    public static void main(String[] args) {
        //stopByFlag();
        //pauseByFlag();
        //jqByJoin();
        stopByInterrupt();
    }

    //场景一 停止   线程在预设的地点检测flag，来决定是否停止。
    static void stopByFlag() {
        ARunnable ar = new ARunnable();
        new Thread(ar).start();
        ar.tellToStop();
    }

    static class ARunnable implements Runnable {

        volatile boolean stop;

        void tellToStop() {
            stop = true;
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("进入不可停止区域 1。。。");
            Thread.sleep(5000);
            System.out.println("退出不可停止区域 1。。。");
            System.out.println("检测标志stop = " + String.valueOf(stop));
            if (stop) {
                System.out.println("停止执行");
                return;
            }
            System.out.println("进入不可停止区域 2。。。");
            Thread.sleep(5000);
            System.out.println("退出不可停止区域 2。。。");

        }

    }

    //场景二  暂停/恢复   还是在预设的地点检测flag。然后就是wait/notify配合使用。
    @SneakyThrows
    static void pauseByFlag() {
        BRunnable br = new BRunnable();
        new Thread(br).start();
        br.tellToPause();
        Thread.sleep(8000);
        br.tellToResume();
    }

    static class BRunnable implements Runnable {

        volatile boolean pause;

        void tellToPause() {
            pause = true;
        }

        void tellToResume() {
            synchronized (this) {
                this.notify();
            }
        }

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("进入不可暂停区域 1。。。");
            Thread.sleep(5000);
            System.out.println("退出不可暂停区域 1。。。");
            System.out.println("检测标志pause = " + String.valueOf(pause));
            if (pause) {
                System.out.println("暂停执行");
                try {
                    synchronized (this) {
                        this.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("恢复执行");
            }
            System.out.println("进入不可暂停区域 2。。。");
            Thread.sleep(5000);
            System.out.println("退出不可暂停区域 2。。。");
        }

    }

    //场景三，插队  join方法可以让某个线程插到自己前面，等它执行完，自己才会继续执行。
    @SneakyThrows
    static void jqByJoin() {
        CRunnable cr = new CRunnable();
        Thread t = new Thread(cr);
        t.start();
        Thread.sleep(1000);
        t.join();
        System.out.println("终于轮到我了");
    }

    static class CRunnable implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("进入不可暂停区域 1。。。");
            Thread.sleep(5000);
            System.out.println("退出不可暂停区域 1。。。");
        }

    }
    //场景四，叫醒 线程在sleep或wait时，是处于无法交互的状态的，此时只能使用interrupt方法中断它，线程会被激活并收到中断异常。
    @SneakyThrows
    static void stopByInterrupt() {
        DRunnable dr = new DRunnable();
        Thread t = new Thread(dr);
        t.start();
        Thread.sleep(2000);
        t.interrupt();
    }

    static class DRunnable implements Runnable {

        @Override
        public void run() {
            System.out.println("进入暂停。。。");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("收到中断异常。。。");
                System.out.println("做一些相关处理。。。");
            }
            System.out.println("继续执行或选择退出。。。");
        }

    }

}
